ICE Store - Plataforma de venda de jogos¶

Parte 1 - Importação de Dados e Preparação dos Dados:¶
In [40]:
# Importando bibliotecas
import pandas as pd
import plotly.express as px
from scipy import stats as st
import plotly.io as pio
pio.renderers.default = "notebook"

# Lendo o dataset
games = pd.read_csv('../data/games.csv')
In [41]:
# Exibindo informações do dataset
games.info()
<class 'pandas.DataFrame'>
RangeIndex: 16715 entries, 0 to 16714
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   Name             16713 non-null  str    
 1   Platform         16715 non-null  str    
 2   Year_of_Release  16446 non-null  float64
 3   Genre            16713 non-null  str    
 4   NA_sales         16715 non-null  float64
 5   EU_sales         16715 non-null  float64
 6   JP_sales         16715 non-null  float64
 7   Other_sales      16715 non-null  float64
 8   Critic_Score     8137 non-null   float64
 9   User_Score       10014 non-null  str    
 10  Rating           9949 non-null   str    
dtypes: float64(6), str(5)
memory usage: 1.4 MB

Na nossa tabela encontramos diversos valores ausentes, alguns deles podendo ter sido gerados por erros de armazenamento no banco de dados, como também por falta de informações que poderiam estar em processo de levantamento (atualização), como as notas dos usuários de jogos vendidos recentemente.

  • A coluna "user_score", possui dados ausentes e dados nomeados como "tbd" ou "To be determined", e com isso nossa coluna possui dados do tipo object, para nossa análise precisamos que ela se apresente com tipo float, realizaremos a conversão dos dados, utilizando o parâmetro errors='coerce' da função pd.to_numeric(). Com isso todos os valores 'tbd' se tornam NaN, se houver algum valor numérico em string por exemplo: '7.5' será convertido normalmente para float64, os NaN se manterão os mesmo e nossos valores númericos datados como object passarão a float64.
In [42]:
# Passando o nome das colunas para o padrão snake_case (todas as letras minúsculas e separadas por underline)

# criando uma lista vazia para os novos nomes
new_columns = [] 
# pequeno ciclo para acessar os nomes das colunas
for old_names in games.columns:
    # convertendo as colunas do dateset com o método lower() 
    name_lowered = old_names.lower()
    # atribuindo os nomes minúsculos a nossa lista "new_columns" 
    new_columns.append(name_lowered) 
# atribuindo a lista com os novos nomes as colunas do Dataset.
games.columns = new_columns 

# imprindo as informações do dataset atualizado
print(games.info())
<class 'pandas.DataFrame'>
RangeIndex: 16715 entries, 0 to 16714
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   name             16713 non-null  str    
 1   platform         16715 non-null  str    
 2   year_of_release  16446 non-null  float64
 3   genre            16713 non-null  str    
 4   na_sales         16715 non-null  float64
 5   eu_sales         16715 non-null  float64
 6   jp_sales         16715 non-null  float64
 7   other_sales      16715 non-null  float64
 8   critic_score     8137 non-null   float64
 9   user_score       10014 non-null  str    
 10  rating           9949 non-null   str    
dtypes: float64(6), str(5)
memory usage: 1.4 MB
None
In [43]:
# Verificando dados ausentes na tabela
ausentes = games.isna().sum()
ausentes
Out[43]:
name                  2
platform              0
year_of_release     269
genre                 2
na_sales              0
eu_sales              0
jp_sales              0
other_sales           0
critic_score       8578
user_score         6701
rating             6766
dtype: int64
In [44]:
# Corrigindo dados ausentes na coluna "name"

# criando uma máscara para os dados ausentes na coluna "name"
miss_names = ~games['name'].isna()
# filtrando a coluna com os dados não ausentes
games_filtered = games[miss_names]
In [45]:
# Removendo dados ausentes da coluna "year_of_release"

# criando uma máscara para os dados ausentes na coluna "year_of_release"
games_years = ~games_filtered['year_of_release'].isna()
# filtrando a coluna com os dados não ausentes
games_filtered = games_filtered[games_years].copy()
# convertendo a coluna "year_of_release" para o Dtype - int
games_filtered['year_of_release'] = games_filtered['year_of_release'].astype('int')

# imprimindo as informações da tabela atualizada
print(games_filtered.info())
<class 'pandas.DataFrame'>
Index: 16444 entries, 0 to 16714
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   name             16444 non-null  str    
 1   platform         16444 non-null  str    
 2   year_of_release  16444 non-null  int64  
 3   genre            16444 non-null  str    
 4   na_sales         16444 non-null  float64
 5   eu_sales         16444 non-null  float64
 6   jp_sales         16444 non-null  float64
 7   other_sales      16444 non-null  float64
 8   critic_score     7983 non-null   float64
 9   user_score       9839 non-null   str    
 10  rating           9768 non-null   str    
dtypes: float64(5), int64(1), str(5)
memory usage: 1.5 MB
None
In [46]:
# Convertendo a coluna de object para float sem atribuir novos valores à NaN e 'tbd'
games_filtered['user_score'] = pd.to_numeric(games_filtered['user_score'], errors='coerce')
# imprimindo as informações da tabela filtrada
print(games_filtered.info())
<class 'pandas.DataFrame'>
Index: 16444 entries, 0 to 16714
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   name             16444 non-null  str    
 1   platform         16444 non-null  str    
 2   year_of_release  16444 non-null  int64  
 3   genre            16444 non-null  str    
 4   na_sales         16444 non-null  float64
 5   eu_sales         16444 non-null  float64
 6   jp_sales         16444 non-null  float64
 7   other_sales      16444 non-null  float64
 8   critic_score     7983 non-null   float64
 9   user_score       7463 non-null   float64
 10  rating           9768 non-null   str    
dtypes: float64(6), int64(1), str(4)
memory usage: 1.5 MB
None
In [47]:
# Calculando o total de vendas para os jogos e atribuindo a uma nova coluna

# criando a coluna "global_sales" e atribuindo a soma das vendas de cada região
games_filtered['global_sales'] = games_filtered['na_sales'] + games_filtered['eu_sales'] + games_filtered['jp_sales'] + games_filtered['other_sales']
# imprimindo primeiras 5 linhas danova coluna "global_sales"
games_filtered['global_sales'].head()
Out[47]:
0    82.54
1    40.24
2    35.52
3    32.77
4    31.38
Name: global_sales, dtype: float64
Parte 2 - Análise exploratória de dados (EDA):¶
In [48]:
# Verificando quantos jogos foram lançados por ano

# utilizando .value_counts() para contar a quantidade de jogos lançados em cada ano 
# e o sort_index para ordernar em ordem crescente.
games_per_year = games_filtered['year_of_release'].value_counts().sort_index()
# imprimindo nossa variável com os valores gerados.
print(games_per_year.head())
year_of_release
1980     9
1981    46
1982    36
1983    17
1984    14
Name: count, dtype: int64
In [49]:
# Vendas totais por plataforma
platform_sales = games_filtered.groupby('platform')['global_sales'].sum().sort_values(ascending=False)
# media das vendas por plataforma
platform_mean = games_filtered.groupby('platform')['global_sales'].mean().sort_values(ascending=False)
# mediana das vendas por plataforma
platform_median = games_filtered.groupby('platform')['global_sales'].median().sort_values(ascending=False)
# quantidade de jogos por plataforma
platform_count = games_filtered.groupby('platform').size().sort_values(ascending=False)

# cálculo para as plataformas
platform_analysis = games_filtered.groupby('platform')['global_sales'].agg([
    'sum',      # Total de vendas
    'mean',     # Média
    'median',   # Mediana
    'count'     # Número de jogos
]).round(2)

# ordenando por vendas totais
platform_analysis = platform_analysis.sort_values('sum', ascending=False)
print(platform_analysis.head(10))
              sum  mean  median  count
platform                              
PS2       1233.56  0.58    0.23   2127
X360       961.24  0.78    0.28   1232
PS3        931.34  0.71    0.28   1306
Wii        891.18  0.69    0.19   1286
DS         802.78  0.38    0.11   2121
PS         727.58  0.61    0.26   1190
PS4        314.14  0.80    0.20    392
GBA        312.88  0.39    0.16    811
PSP        289.53  0.24    0.09   1193
3DS        257.81  0.50    0.12    512
In [50]:
# Filtro de plataformas com vendas totais superiores a US$ 500M
best_platform = platform_sales[platform_sales > 500.00].index

print("Plataformas com vendas > US$ 500M: {}".format(best_platform.tolist()))
Plataformas com vendas > US$ 500M: ['PS2', 'X360', 'PS3', 'Wii', 'DS', 'PS']
  • Abaixo iremos analisar as vendas das plataformas agrupadas por ano de lançamento dos jogos
In [51]:
# Agrupando por plataforma e ano de lançamento, e somando as vendas globais
platform_evolution = games_filtered.groupby(['year_of_release', 'platform'])['global_sales'].sum()
# transformando a série em um DataFrame e preenchendo os valores ausentes com 0
sales_timeline = platform_evolution.unstack(fill_value=0)
# visualizar evolução de vendas

fig = px.bar(sales_timeline[best_platform], 
            title='Evolução nas vendas das Plataformas',
            labels={'value': 'Vendas Globais (milhões)',
            'year_of_release': 'Ano de Lançamento',
            'platform': 'Plataforma'})
fig.show()
In [52]:
# Filtrando as plataformas que deixaram de vender ao longo dos anos

# anos escolhidos para verificação
recent_years = [2014, 2015, 2016] 
# lista que irá conter os dados filtrado no laço abaixo
old_platforms = [] 
# ciclo para verificar as plataformas que tiveram vendas no passado, mas não tiveram vendas recentes
for platform in games_filtered['platform'].unique():
    # verificando se há vendas no passado
    old_sales = platform_evolution[platform_evolution.index.get_level_values('platform') == platform]
    # verificar se não tem vendas recentes
    recent_sales = old_sales[old_sales.index.get_level_values('year_of_release').isin(recent_years)]
    # verificando a quantidade de vendas dos filtros com IF
    if len(old_sales) > 0 and len(recent_sales) == 0:
        # atribuindo as plataformas a lista
        old_platforms.append(platform)
# imprimindo as plataformas que deixaram de ser populares
print("Plataformas que deixaram de ser populares: {} ".format(old_platforms))
Plataformas que deixaram de ser populares: ['NES', 'GB', 'DS', 'PS2', 'SNES', 'GBA', 'N64', 'PS', 'XB', '2600', 'GC', 'GEN', 'DC', 'SAT', 'SCD', 'WS', 'NG', 'TG16', '3DO', 'GG', 'PCFX'] 
In [53]:
# Selecionando algumas plataformas
selected_platforms = ['PS2', 'XB', 'PS', 'NES', 'N64']

# visualizando a evolução das vendas por plataforma ao longo do tempo
fig2 = px.line(sales_timeline[selected_platforms],
               title='Evolução das Vendas por Plataforma ao Longo do Tempo',
               labels={'value': 'Vendas Totais (milhões USD)', 'year_of_release': 'Ano',
                       'platform': 'Plataforma'},
                markers=True,
                line_shape='spline')
fig2.show()
In [54]:
# Calcular primeiro e último ano para cada plataforma

# agrupando por plataforma e calculando o primeiro e último ano de lançamento, além do total de jogos
platforms = games_filtered.groupby('platform')['year_of_release'].agg([
     ('first_year', 'min'),
     ('last_year', 'max'),
     ('games_total', 'count')
 ]).reset_index()
# calculando duração das plataformas
platforms['platform_duration'] = platforms['last_year'] - platforms['first_year']
In [55]:
# Imprimindo a mediana de duração das plataformas
print('===MEDIANA DE DURAÇÃO DAS PLATAFORMAS===')
# utilizando o método median() para calcular a mediana da coluna "platform_duration" e formatando a saída
print('{:.0f} anos'.format(platforms['platform_duration'].median()))
===MEDIANA DE DURAÇÃO DAS PLATAFORMAS===
6 anos
  • Acima criamos gráficos com algumas plataformas com as maiores quantidade de vendas (populares) em seus anos de atividade, e também observamos a queda das mesmas em trocas geracionais, por exemplo: PS (playstation 1) para o PS2 (playstation 2). Como também encontramos a mediana geracional entre as plataformas, na qual temos uma diferença de 6 anos para uma nova plataforma surgir, e a sua antecessora começar a recuar em vendas até ser descontinuada, explicitamente quando deixam de ser lançados novos jogos para a mesma.

  • Portanto para a continuidade das nossas análises, escolhemos os últimos 4 anos de vendas, pois entendemos que esses anos se encontram durante as transições das antigas e novas plataformas de gigantes da tecnologia, como Nintendo, Microsoft e Sony.

In [56]:
# Filtrar dados para o período escolhido
recent_data = games_filtered[games_filtered['year_of_release'].isin([2013, 2014, 2015, 2016])]
# filtrando plaformas com mais de 1 milhão em vendas no mercado global
recent_data_1 = recent_data[recent_data['global_sales'] > 1.0]
# agrupando os dados
new_platforms = recent_data_1.groupby(['year_of_release', 'platform'])['global_sales'].sum()
# transformando os dados em uma tabela pivô
recent_sales = new_platforms.unstack(fill_value=0)
# criando gráfico de barras para melhor visualizar
fig3 = px.bar(recent_sales,
              title='Evolução nas vendas das Plataformas (2013-2016)',
              labels={'value': 'Vendas Globais (milhões USD)',
                      'year_of_release': 'Ano de Lançamento',
                      'platform': 'Plataforma'},
              barmode='group')
fig3.show()
  • Acima visualizamos o últimos 4 anos de vendas das plataformas que obtiveram mais de 1 milhão em vendas globais.

  • Em 2013 as vendas são lideradas pelo PS3, Xbox 360 e 3DS. Ainda em 2013, observamos o lançamento de novas plataformas, como PS4, Xbox One, WiiU. Em 2014 há inversão no total de vendas de duas plataformas, PS3 e X360 com PS4 e XOne, sendo as duas últimas a nova geração que vieram para substituir seus antecessores.

  • Entre 2013 e 2016 tivemos uma queda gradativa nas vendas do 3DS.

  • Em 2016, temos 4 plataformas que ultrapassaram 1 milhão em vendas. E comparado aos anos anteriores, observamos grande queda nas vendas de todas as plaformas.

In [57]:
# Selecionando as plataformas desejadas
potencial_sales = recent_sales[['3DS', 'PC', 'PS4', 'WiiU', 'XOne']]

# calculando variância e desvio padrão
variance_sales = potencial_sales.var()
desvio_sales = potencial_sales.std()
# imprimindo análise de variabilidade das plataformas
print("=== ANÁLISE DE VARIABILIDADE DAS PLATAFORMAS (2013-2016) ===")
print("Número de anos analisados: {}".format(len(potencial_sales)))
print("Plataformas analisadas: {}".format(list(potencial_sales.columns)))
# imprimindo a variância para cada plataforma
print("\n=== VARIÂNCIA ===")
for platform, var in variance_sales.items():
    print(f"{platform}: {var:.2f}")
# imprimindo o desvio padrão para cada plataforma
print("\n=== DESVIO PADRÃO ===")
for platform, std in desvio_sales.items():
    print(f"{platform}: {std:.2f}")
=== ANÁLISE DE VARIABILIDADE DAS PLATAFORMAS (2013-2016) ===
Número de anos analisados: 4
Plataformas analisadas: ['3DS', 'PC', 'PS4', 'WiiU', 'XOne']

=== VARIÂNCIA ===
3DS: 254.23
PC: 4.25
PS4: 1066.77
WiiU: 34.60
XOne: 263.22

=== DESVIO PADRÃO ===
3DS: 15.94
PC: 2.06
PS4: 32.66
WiiU: 5.88
XOne: 16.22
In [58]:
# Coeficiente de variação para comparar consistência
cv_sales = (desvio_sales / potencial_sales.mean()) * 100
print("\n=== COEFICIENTE DE VARIAÇÃO (%) ===")
print("(Menor valor = maior consistência)")
print(cv_sales.sort_values())
print()
# imprimindo os dados estatísticos com o método .describe()
print('=== Imprimindo os dados estatísticos ===')
print(potencial_sales.describe().round(2))
=== COEFICIENTE DE VARIAÇÃO (%) ===
(Menor valor = maior consistência)
platform
PS4     53.629159
XOne    56.480796
WiiU    57.666452
3DS     64.325335
PC      74.045789
dtype: float64

=== Imprimindo os dados estatísticos ===
platform    3DS    PC    PS4   WiiU   XOne
count      4.00  4.00   4.00   4.00   4.00
mean      24.79  2.78  60.90  10.20  28.72
std       15.94  2.06  32.66   5.88  16.22
min        8.47  0.00  22.74   2.04  14.55
25%       13.39  1.84  39.53   8.41  15.06
50%       23.66  3.34  64.24  11.42  27.17
75%       35.06  4.29  85.62  13.22  40.84
max       43.36  4.45  92.38  15.91  46.01
In [59]:
# Criando um boxplot para vendas globais das plataformas
fig4 = px.box(potencial_sales,
              title='Vendas Globais por Plataforma (2013-2016)',
              labels={'value': 'Vendas Globais (milhões USD)', 'variable': 'Plataforma',
                      'platform': 'Plataformas'})
fig4.show()
  • No boxplot criado acima, observamos os últimos 4 anos de vendas das 5 plataformas com potencial de crescimento para 2017.

  • Estes são o 3DS e PC por terem uma duração maior, o 3DS vem recebendo novas versões ao longo dos anos e mantendo médias altas de vendas no segmento de handheld, e o PC por ser de plataforma aberta e versátil, assim entregando consistência em suas vendas no passar dos anos.

  • O PS4, XOne e WiiU por serem a nova geração de consoles das maiores desenvolvedoras, e estarem no inicio da sua vida geracional.

  • A diferença nas vendas entre as 5 plataformas em questão são significativas, com o PS4 alcançando máximas maiores, mantendo uma média de venda nos 4 anos de 60 milhões, sendo acompanhado pelo XOne e 3DS com médias e máximas bem próximas na casa dos 24 - 28 milhões na média e 43 - 46 milhões nas máximas.

In [60]:
# Filtrando os dados para a plataforma PS4
ps4 = recent_data[recent_data['platform'] == 'PS4']
In [61]:
# Criando gráfico de dispersão interativo
top_30_ps4 = ps4.nlargest(30, 'global_sales')

fig = px.scatter(top_30_ps4, x='global_sales', y='name',
                 title='Top 30 Jogos PS4 - Vendas Globais',
                 labels={'global_sales':'Vendas Globais (milhões USD)', 'name':'Jogos'},
                 hover_data=['user_score', 'critic_score'])
fig.update_layout(
    width=1000,
    height=900,
    font=dict(size=12)
)
fig.show()
In [62]:
# calculando a correlação na tabela da plataforma PS4
ps4_corr = ps4.corr(numeric_only=True)
# exibindo a matriz de correlação
print('=== Matriz de Correlação para PS4 ===')
ps4_corr
=== Matriz de Correlação para PS4 ===
Out[62]:
year_of_release na_sales eu_sales jp_sales other_sales critic_score user_score global_sales
year_of_release 1.000000 -0.248961 -0.208306 -0.060993 -0.234796 -0.021142 0.152447 -0.235032
na_sales -0.248961 1.000000 0.785362 0.472981 0.944259 0.415008 -0.020933 0.928160
eu_sales -0.208306 0.785362 1.000000 0.464563 0.944698 0.346720 -0.048925 0.958157
jp_sales -0.060993 0.472981 0.464563 1.000000 0.496467 0.322358 0.171332 0.527129
other_sales -0.234796 0.944259 0.944698 0.496467 1.000000 0.409191 -0.035639 0.998051
critic_score -0.021142 0.415008 0.346720 0.322358 0.409191 1.000000 0.557654 0.406568
user_score 0.152447 -0.020933 -0.048925 0.171332 -0.035639 0.557654 1.000000 -0.031957
global_sales -0.235032 0.928160 0.958157 0.527129 0.998051 0.406568 -0.031957 1.000000
In [63]:
# Analisando apenas jogos com dados de user_score
ps4_user = ps4[ps4['user_score'] != 'NaN']  # Remove valores NaN
print(f"Jogos com dados originais na coluna 'user_score': {len(ps4_user)}")

# Calcular correlação
if len(ps4_user) > 10:  # Se tiver dados suficientes
    corr_user = ps4_user[['user_score', 'global_sales']].corr()
    print("\nCorrelação com dados originais:")
    print(corr_user)
Jogos com dados originais na coluna 'user_score': 392

Correlação com dados originais:
              user_score  global_sales
user_score      1.000000     -0.031957
global_sales   -0.031957      1.000000
In [64]:
# Analisando apenas jogos com dados de critic_score
ps4_critic = ps4[ps4['critic_score'] != 'NaN'] # Remove valores NaN
print(f"Jogos com dados originais 'critic_score': {len(ps4_critic)}")

# Calcular correlação
if len(ps4_critic) > 10:  # Se tiver dados suficientes
    corr_critic = ps4_critic[['critic_score', 'global_sales']].corr()
    print("\nCorrelação com dados originais:")
    print(corr_critic)
Jogos com dados originais 'critic_score': 392

Correlação com dados originais:
              critic_score  global_sales
critic_score      1.000000      0.406568
global_sales      0.406568      1.000000
In [65]:
# Gráfico de dispersão para critic_score x vendas
fig5 = px.scatter(ps4, x='critic_score', y='global_sales',
                  title='Relação: Nota dos Críticos vs Vendas Globais (PS4)',
                  labels={'critic_score':'Nota dos Críticos', 
                         'global_sales':'Vendas Globais (milhões USD)'},
                  hover_data=['name'])
fig5.show()

# Gráfico de dispersão para user_score x vendas  
fig6 = px.scatter(ps4, x='user_score', y='global_sales',
                  title='Relação: Nota dos Usuários vs Vendas Globais (PS4)',
                  labels={'user_score':'Nota dos Usuários',
                         'global_sales':'Vendas Globais (milhões USD)'},
                  hover_data=['name'])
fig6.show()

Cálculos de correlação

  • Encontramos uma correlação positiva moderada (0.406) entre a coluna 'critic_score' e as vendas globais da plataforma PS4, indicando assim que avaliações mais altas dos profissionais críticos tendem a resultar em vendas maiores, mesmo sendo apenas uma relação moderada, ainda continua significativa.
  • Em relação as avaliações dos usuários (user_score), temos uma correlação quase zero (-0.0319) com as vendas globais do PS4, indicando que essas notas não influenciam muito nas vendas.
In [66]:
# Comparando as vendas dos mesmos jogos em outras plataformas.

# filtrando o nome dos jogos
games_filter = ps4['name']

# filtrando a tabela pelo nome dos jogos que queremos analisar.
games_sales = recent_data[recent_data['name'].isin(games_filter)]

# filtrando plataformas diferentes do PS4
games_others_plat = games_sales[games_sales['platform'] != 'PS4'] 

# verificando quantos jogos do PS4 existem em outras plataformas
print(f"Jogos no PS4: {ps4['name'].nunique()}")
print(f"Jogos do PS4 encontrados em outras plataformas: {games_others_plat['name'].nunique()}")
Jogos no PS4: 392
Jogos do PS4 encontrados em outras plataformas: 316
In [67]:
# Criando gráfico de dispersão interativo para jogos do PS4 em outras plataformas
top_30_plat = games_others_plat.nlargest(30, 'global_sales')

fig7 = px.scatter(top_30_plat, x='global_sales', y='name',
                 title='Jogos em outras plataformas - Vendas Globais',
                 labels={'global_sales':'Vendas Globais (milhões USD)', 'name':'Jogos'},
                 hover_data=['user_score', 'critic_score', 'platform'])
fig7.update_layout(
    width=1000,
    height=900,
    font=dict(size=12)
)
fig7.show()
In [68]:
# Jogos que encontramos na plataforma PS4 com maiores diferenças de vendas em outras plataformas

# imprimindo o título para a análise
print("Top 30 jogos com maiores vendas em outras plataformas:\n")
# utilizando o método nlargest para encontrar os 30 jogos com maiores vendas em outras plataformas 
# e exibindo as colunas de interesse
top_others = games_others_plat.nlargest(30, 'global_sales')[['name', 'platform', 'global_sales']]
# imprimindo os resultados
print(top_others.head())
Top 30 jogos com maiores vendas em outras plataformas:

                    name platform  global_sales
16    Grand Theft Auto V      PS3         21.05
23    Grand Theft Auto V     X360         16.27
60  Call of Duty: Ghosts     X360         10.24
69  Call of Duty: Ghosts      PS3          9.36
72             Minecraft     X360          9.18
In [69]:
# Distribuição de vendas globais e regionais por gênero

# agrupando por gênero e somando as vendas globais e regionais
genre = games_filtered.groupby('genre')[['global_sales', 'na_sales', 'eu_sales', 'jp_sales', 'other_sales']].sum()
# imprimindo a distribuição de vendas por gênero
print("*** DISTRIBUIÇÃO DE VENDAS POR GÊNERO ***\n")
print(genre)
*** DISTRIBUIÇÃO DE VENDAS POR GÊNERO ***

              global_sales  na_sales  eu_sales  jp_sales  other_sales
genre                                                                
Action             1716.52    863.17    510.99    160.14       182.22
Adventure           233.33    101.52     63.20     52.24        16.37
Fighting            442.66    220.51     99.00     87.28        35.87
Misc                790.29    399.57    210.60    107.02        73.10
Platform            825.55    444.44    199.39    130.71        51.01
Puzzle              239.89    121.13     49.78     56.68        12.30
Racing              723.49    356.86    234.49     56.63        75.51
Role-Playing        931.08    330.04    188.24    353.39        59.41
Shooter            1041.36    584.83    314.52     38.68       103.33
Simulation          387.96    180.40    113.35     63.64        30.57
Sports             1309.67    671.20    371.33    134.93       132.21
Strategy            172.57     67.75     44.79     49.30        10.73
In [70]:
# Análise mais completa das vendas globais por gênero
genre_analysis = games_filtered.groupby('genre').agg({
    'global_sales': ['sum', 'mean', 'median', 'count']}).round(2)

# simplificando os nomes das colunas
genre_analysis.columns = ['total_sales', 'mean_sales', 'median_sales', 'game_count']
genre_analysis = genre_analysis.sort_values('total_sales', ascending=False)
# imprimindo a análise completa por gênero
print("*** ANÁLISE COMPLETA POR GÊNERO ***\n")
print(genre_analysis)
*** ANÁLISE COMPLETA POR GÊNERO ***

              total_sales  mean_sales  median_sales  game_count
genre                                                          
Action            1716.52        0.52          0.19        3307
Sports            1309.67        0.57          0.22        2306
Shooter           1041.36        0.80          0.24        1296
Role-Playing       931.08        0.63          0.18        1481
Platform           825.55        0.94          0.27         878
Misc               790.29        0.46          0.16        1721
Racing             723.49        0.59          0.19        1226
Fighting           442.66        0.53          0.21         837
Simulation         387.96        0.45          0.15         857
Puzzle             239.89        0.42          0.10         569
Adventure          233.33        0.18          0.05        1293
Strategy           172.57        0.26          0.10         673
In [71]:
# Verificando a média das notas por gênero
genre_grade = games_filtered.groupby('genre')[['user_score', 'critic_score']].mean().round(2)
# imprimindo a média das notas por gênero
print("*** NOTAS POR GÊNERO ***\n")
print(genre_grade)
*** NOTAS POR GÊNERO ***

              user_score  critic_score
genre                                 
Action              7.06         66.68
Adventure           7.14         65.27
Fighting            7.30         69.16
Misc                6.81         66.65
Platform            7.31         68.12
Puzzle              7.14         67.23
Racing              7.04         68.01
Role-Playing        7.62         72.66
Shooter             7.05         70.26
Simulation          7.13         68.61
Sports              6.95         71.99
Strategy            7.29         72.16
  • Seguindo o enunciado, encontramos os 3 maiores gêneros em vendas: Action, Sports, Shooter

  • E os 3 menos vendidos: Puzzle, adventure e strategy

  • Os dois primeiros gêneros mais vendidos possuem uma grande contagem de jogos, isso influência em uma quantidade maior de receita em vendas. Mas também sabemos que esses dois primeiros jogos atraem mais compradores por serem jogos que exploram o instinto humano de competição e curiosidade. Os jogos de gênero shooter entregam adrenalina e desafio em sobreviver em uma missão perigosa como em call of duty e battlefield.

  • Com isso as vendas de cada gênero irá depender do gosto do usuário e também da qualidade do título lançado, pois jogos bem produzidos acabam por receber notas boas e assim despertam interesse em usuários que normalmente não comprariam.

  • Em relação aos 3 gêneros menos vendidos citados acima, as vendas deles estão estritamente ligadas a baixa procura, sendo assim gêneros nichados, pois mesmo com média de notas criticas e de usuários em bons números, observamos que as vendas não atingem altos valores, como também não encontramos diferenças nas vendas por região para tais gêneros.

Parte 3 - Criação de Perfis de Utilizador por Região:¶
In [72]:
# Função criada para separar cada região unicamente e exibir o resultado desejado.
def perfil_regiao(regiao):
    # 5 plataformas principais
    plat_sales = recent_data.groupby('platform')[regiao].sum().sort_values(ascending=False).head(5)
    
    # 5 principais gêneros  
    genre_sales = recent_data.groupby('genre')[regiao].sum().sort_values(ascending=False).head(5)
    
    # vendas por Rating
    rating_sales = recent_data.groupby('rating')[regiao].sum().sort_values(ascending=False)
    
    # criando DataFrames organizados
    plat_df = pd.DataFrame({
        'Plataforma': plat_sales.index,
        'Vendas (milhões)': plat_sales.values
    }).reset_index(drop=True)
    
    genre_df = pd.DataFrame({
        'Gênero': genre_sales.index,
        'Vendas (milhões)': genre_sales.values
    }).reset_index(drop=True)
    
    rating_df = pd.DataFrame({
        'Rating': rating_sales.index,
        'Vendas (milhões)': rating_sales.values
    }).reset_index(drop=True)
    
    return {
        'plataformas': plat_df,
        'generos': genre_df,
        'ratings': rating_df
    }
In [73]:
# Chamando a função para região NA
perfil_na = perfil_regiao('na_sales')
# Exibindo o perfil de usuário para a região NA
print("=== PERFIL DE USUÁRIO - AMÉRICA DO NORTE ===\n")
print(" TOP 5 PLATAFORMAS:")
print(perfil_na['plataformas'])
print("\n TOP 5 GÊNEROS:")
print(perfil_na['generos'])
print("\n VENDAS POR RATING:")
print(perfil_na['ratings'])
=== PERFIL DE USUÁRIO - AMÉRICA DO NORTE ===

 TOP 5 PLATAFORMAS:
  Plataforma  Vendas (milhões)
0        PS4            108.74
1       XOne             93.12
2       X360             81.66
3        PS3             63.50
4        3DS             38.20

 TOP 5 GÊNEROS:
         Gênero  Vendas (milhões)
0        Action            126.05
1       Shooter            109.74
2        Sports             65.27
3  Role-Playing             46.40
4          Misc             27.49

 VENDAS POR RATING:
  Rating  Vendas (milhões)
0      M            165.21
1      E             79.05
2   E10+             54.24
3      T             49.79
In [74]:
# Chamando a função para região EU
perfil_eu = perfil_regiao('eu_sales')
# Exibindo o perfil de usuário para a região EU
print("=== PERFIL DE USUÁRIO - EUROPA ===\n")
print(" TOP 5 PLATAFORMAS:")
print(perfil_eu['plataformas'])
print("\n TOP 5 GÊNEROS:")
print(perfil_eu['generos'])
print("\n VENDAS POR RATING:")
print(perfil_eu['ratings'])
=== PERFIL DE USUÁRIO - EUROPA ===

 TOP 5 PLATAFORMAS:
  Plataforma  Vendas (milhões)
0        PS4            141.09
1        PS3             67.81
2       XOne             51.59
3       X360             42.52
4        3DS             30.96

 TOP 5 GÊNEROS:
         Gênero  Vendas (milhões)
0        Action            118.13
1       Shooter             87.86
2        Sports             60.52
3  Role-Playing             36.97
4        Racing             20.19

 VENDAS POR RATING:
  Rating  Vendas (milhões)
0      M            145.32
1      E             83.36
2   E10+             42.69
3      T             41.95
In [75]:
# Chamando a função para região JP
perfil_jp = perfil_regiao('jp_sales')
# Exibindo o perfil de usuário para a região JP
print("=== PERFIL DE USUÁRIO - JAPÃO ===\n")
print(" TOP 5 PLATAFORMAS:")
print(perfil_jp['plataformas'])
print("\n TOP 5 GÊNEROS:")
print(perfil_jp['generos'])
print("\n VENDAS POR RATING:")
print(perfil_jp['ratings'])
=== PERFIL DE USUÁRIO - JAPÃO ===

 TOP 5 PLATAFORMAS:
  Plataforma  Vendas (milhões)
0        3DS             67.81
1        PS3             23.35
2        PSV             18.59
3        PS4             15.96
4       WiiU             10.88

 TOP 5 GÊNEROS:
         Gênero  Vendas (milhões)
0  Role-Playing             51.04
1        Action             40.49
2          Misc              9.20
3      Fighting              7.65
4       Shooter              6.61

 VENDAS POR RATING:
  Rating  Vendas (milhões)
0      T             20.59
1      E             15.14
2      M             14.11
3   E10+              5.89

Acima criamos uma função para filtrar separadamente as regiões e as mostramos em formato de tabela para melhor visualização entre plataformas, generos, ratings e seus valores de vendas.

  • Nos mercados da América do Norte e Europa encontramos um padrão em relação aos pontos analisados, apenas havendo uma única diferença no quinto gênero mais vendido nos dois mercados, onde na América temos o gênero misc e na Europa o gênero racing.
  • Já no mercado Japonês vemos uma maior diferença, possivelmente ligado a cultura e costumes regionais, onde observamos a preferência dos usuários por plataformas handheld (3DS e PSV), jogos do genero RPG (Role-Playing). E apenas no caso do japão, as vendas parecem ser afetadas pelo rating, já que as maiores vendas relatadas somam 20 milhões com rating T (teen) e 15 milhões (everyone), mas isso possivelmente está ligado aos valores ausentes que encontramos na coluna 'rating' do nosso dataset original.
Parte 4 - Teste de Hipóteses Estatísticas:¶

PRIMEIRO CENÁRIO - As hipóteses escolhidas são:

  • Hipótese nula: As classificações médias dos usuários das plataformas Xbox One e PC são as mesmas.
  • Hipótese alternativa: As classificações médias dos usuários das plataformas Xbox One e PC são as diferentes.

Escolhemos o teste estatístico da Hipótese sobre a igualdade das médias de duas populações.

Nosso valor alpha será: 5% ou 0.05

In [76]:
# Testando as hipóteses do primeiro cenário
xbox_one = recent_data[recent_data['platform'] == 'XOne']
pc = recent_data[recent_data['platform'] == 'PC']

# filtrando apenas valores válidos (não NaN)
xbox_scores = xbox_one['user_score'].dropna().values
pc_scores = pc['user_score'].dropna().values

# realizando teste T
results = st.ttest_ind(xbox_scores, pc_scores)
alpha = 0.05

# imprimindo os resultados do teste do primeiro cenário
print('*** TESTE DE HIPÓTESE DO PRIMEIRO CENÁRIO ***')
print('p-value: ', results.pvalue)

# interpretando os resultados do teste
if (results.pvalue < alpha):
    print('\nRejeitamos a hipótese nula')
    print('As médias são DIFERENTES')
else:
    print('\nNão podemos rejeitar a hipótese nula')
    print('Não há evidência de diferença significativa')
*** TESTE DE HIPÓTESE DO PRIMEIRO CENÁRIO ***
p-value:  0.14012658403611647

Não podemos rejeitar a hipótese nula
Não há evidência de diferença significativa

SEGUNDO CENÁRIO - As hipóteses escolhidas são:

  • Hipótese nula: As classificações médias de usuários para os gêneros Action (ação) e Sports (esportes) são as mesmas.
  • Hipótese alternativa: As classificações médias de usuários para os gêneros Action (ação) e Sports (esportes) são diferentes.

Escolhemos o teste estatístico da Hipótese sobre a igualdade das médias de duas populações.

Nosso valor alpha será: 5% ou 0.05

In [77]:
# Testando as hipóteses do segundo cenário
action = recent_data[recent_data['genre'] == 'Action']
sports = recent_data[recent_data['genre'] == 'Sports']

# filtrando apenas valores válidos (não NaN)
action_score = action['user_score'].dropna().values
sports_score = sports['user_score'].dropna().values

# realizando teste T
results = st.ttest_ind(action_score, sports_score)
alpha = 0.05

# imprimindo os resultados do segundo cenário
print('*** TESTE DE HIPÓTESE SEGUNDO CENÁRIO ***')
print('p-value: ', results.pvalue)

# interpretando os resultados do teste
if (results.pvalue < alpha):
    print('\nRejeitamos a hipótese nula')
    print('As médias são DIFERENTES')
else:
    print('\nNão podemos rejeitar a hipótese nula')
    print('Não há evidência de diferença significativa')
*** TESTE DE HIPÓTESE SEGUNDO CENÁRIO ***
p-value:  1.0517832389140034e-27

Rejeitamos a hipótese nula
As médias são DIFERENTES
Parte 6 - Conclusão Geral¶

Chegamos a conclusão deste projeto. Estarei explicando e também listando os pontos abordados, como foram tratados os dados e as decisões tomadas que nos guiaram até o fim deste projeto.

  • Iniciamos realizando toda a preparação dos dados, fazendo correções e alterações na tabela principal que achamos necessárias para obter uma análise mais limpa e bem organizada. Logo também realizamos diversas filtragens para abranger todos os nossos temas abordados e favorecer nosso processo de análise das vendas, comportamentos e finalização do projeto.
  • Com isso nossas análises indicaram como já citado anteriormente durante o projeto, que novas plataformas possuem uma janela de lançamento de em média 6 anos em relação a sua plataforma antecessora, esse padrão de lançamento é facilmente percebido nas plataformas da Sony, Microsoft e Nintendo. Essas empresas lideram o mercado, com as maiores vendas registradas sendo da Sony, com o console PS2 que ultrapassou a marca dos U$1.2 bilhões de dólares, e cerca de 2127 jogos. Mas ao longo dos anos, como informado são lançados novos consoles, plataformas. Portanto nossas análises se dirigem aos últimos 4 anos de vendas da ICE Store, onde nos deparamos com uma troca geracional de plataformas, analisando os anos entre 2013 e 2016 encontramos vendas que inicialmente eram lideradas pelo PS3 e durante a troca geracional pudemos observar a queda dessas vendas e sendo assumidas pelo seu sucessor, o PS4. O mesmo acontecimento é observado para as plataformas da Microsoft (Xbox) e Nintendo (Wii), mas na Nintendo vemos uma queda gradual nas vendas do seu handheld (3DS).
  • No ano de 2016, observamos uma queda bastante perceptível nas vendas em todas as plataformas, essas quedas podem estar relacionadas aos dados recebidos para análise, já que recebemos uma notificação de que os dados para este ano de 2016 podem estar incompletos. Mesmo assim decidimos por manter esse ano (2016) em nossa abordagem, pois conseguimos observar a dominância nas vendas das plataformas mais recentes, já que as mesma estão no início da sua vida útil. Sendo essas as plataformas com maior potencial em vendas: 3DS, PS4, WiiU, Xbox One e PC, sendo a última plataforma citada a única a não atingir mais de 1 milhão em vendas em 2016, mas sendo um pilar importante pois é a única plataforma aberta, e com maior longevidade entre as demais. Assim a diferença nas vendas entre as 5 plataformas em questão são significativas, com o PS4 alcançando 92 milhões de máxima e mantendo uma média de venda nos 4 anos de 60 milhões, sendo acompanhado pelo XOne e 3DS com médias e máximas bem próximas na casa dos 24 - 28 milhões na média e 43 - 46 milhões nas máximas.
  • Nas análises de gênero e plataformas por região, como já citado, observamos padrões nos resultados, possivelmente ligados a cultura e costumes locais. Esses resultados podem ajudar a ICE Store a criar campanhas promocionais regionais, assim direcionando corretamente marketings para esses públicos com perfis traçados, possibilitando o aumento das vendas para cada região.
  • Por fim, ao realizar nossos testes de hipótese, nos deparamos com o primeiro cenário de que as classificações médias dos usuários das plataformas Xbox One e PC são as mesmas, não havendo base estatística suficiente para afirmar que exista diferenças. Entretanto em nosso segundo cenário de hipótese observamos que existe diferenças estatísticas nas avaliações médias dos usuários para os gêneros Action e Sports, com a média do genêro action maior que o gênero sports, com o gênero action possuindo cerca de mil jogos a mais lançados e sendo também o gênero mais vendido.